var ggkey = "ABQIAAAAlllmAD26h3L10GtRNtQNvxT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSuYa7C4ATOBKsLMHwfbVPAtBdQ3g";
var raffraichissement = 1000;

var Tx = 500;
var Ty = 500;

var diametre = 3;

var svg;



var SelectionLng = new Array(2);
var SelectionLat = new Array(2);

var SelectionLng_prev = new Array(2);
var SelectionLat_prev = new Array(2);




/************  VARIABLES   IMAGES   ********************/
var modele = 'google';//ou bien yahoo, ou bien ign

var imagesUrls = new Array(32);

var imageSVG = new Array(16);//stocke les variables svg//stocke les variables svg des images.
var imageSVGfondu = new Array(16);//stocke les variables svg des images servant au fondu.
var imagePreparees = new Array(16);//stocke des variables d'OBJET javascrip image pour les images à mettre en cache.

var IndiceIM11_x;
var IndiceIM11_y;//le couple d'indices de l'image nord ouest de la mosaique, pour le niveau de zoom = zoom
var zoom;

var indice_prepare_x = -1;
var indice_prepare_y = -1;
var zoom_prepare = -1;
/*******************************************************/



/************ Variables OBJET MOBILE *******************/
var objetMobile = {};
//l'objet objetMobile possède comme champs: name, slug, itinerary, references, x, y, u ,v ,svg

//variables utiles initialisées pour la simulation:
var NombreObjets;
/*******************************************************/



/************  Variables SVG : GROUPS ******************/
var imageSVGgroup;
var pointSVGgroup;
var imageSVGfondugroup;
var tronconSVGgroup;
/*******************************************************/


/************  Variables ITINERAIRE  *******************/
var nbItineraires;
var itineraire;
//l'objet itineraire possède comme champs: name, checkpoints qui est un tableau possédant comme champs: x, y
/*******************************************************/


var fondu = -1;

var selectedItems = {};


/************************************************  CALLBACKS ******************************************************/
/*
callbacks examples, those functions are called from the menu, to do : tags, & syncronisation between objects selected in the menu and objects selected here
all selected items(tag or vehicle) are otherwise in the global variable selectedItems (menu.js), with selectedItems['item_id'] = true if item is selected
selectedItems should be later saved in the server
*/


/******************** PARTIE  MENU  VEHICLES *********************/

var selection_has_changed = false;
var tags = {};
var selected_vehicles = {};


function addVehicleToSelection(vehiculeId){//connected
	selectedItems[objetMobile[vehiculeId].slug] = true;
	selection_has_changed = true;
}


function deleteVehicleFromSelection(vehiculeId){//connected
	selectedItems[objetMobile[vehiculeId].slug] = false;
	selection_has_changed = true;
}


function addTagToSelection(tagId){//connected
	if(inDjango){
		var vehicles = tags[tagId].vehicles;
		for(i = 0; i<vehicles.length; i++){
			objetMobile[vehicles[i]].references ++;
			selectedItems[objetMobile[vehicles[i]].slug] = true;
		}
		selection_has_changed = true;
		selectedItems[tags[tagId].slug] = true;
	}
	else{
		if(selectedItems[tags[tagId].slug] == false){
			var vehicles = tags[tagId].vehicles;
			for(i = 0; i<vehicles.length; i++){
				objetMobile[vehicles[i]].references ++;
				selectedItems[objetMobile[vehicles[i]].slug] = true;
			}
			selection_has_changed = true;
			selectedItems[tags[tagId].slug] = true;
		}
	}
}



function deleteTagFromSelection(tagId){//connected
	if(inDjango){
		var vehicles = tags[tagId].vehicles;
		for(i = 0; i<vehicles.length; i++){
			objetMobile[vehicles[i]].references --;
			if(objetMobile[vehicles[i]].references == 0){
				selectedItems[objetMobile[vehicles[i]].slug] = false;
				//on décide de déselectionner les objets concernés uniquement si aucun autre tag ne le garde sélectionné.
			}
		}
		selectedItems[tags[tagId].slug] = false;
		selection_has_changed = true;
	}
	else{
		if(selectedItems[tags[tagId].slug]){
			var vehicles = tags[tagId].vehicles;
			for(i = 0; i<vehicles.length; i++){
				objetMobile[vehicles[i]].references --;
				if(objetMobile[vehicles[i]].references == 0){
					selectedItems[objetMobile[vehicles[i]].slug] = false;
					//on décide de déselectionner les objets concernés uniquement si aucun autre tag ne le garde sélectionné.
				}
			}
			selectedItems[tags[tagId].slug] = false;
			selection_has_changed = true;
		}
	}
}


function deselectAllVehicles(){//connected, keeps the tags
	$.each(
		objetMobile,
		function(id)
		{
			if(selectedItems[objetMobile[id].slug]){
				selectedItems[objetMobile[id].slug] = false;
			}
		}
	);
	selection_has_changed = true;
}


function deselectAll(){//not connected, erase all
	$.each(
		objetMobile,
		function(id)
		{
			this.references = 0;
		}
	);
	
	$.each(
		selectedItems,
		function(slug)
		{
			selectedItems[slug] = false;
		}
	);
	
	selection_has_changed = true;
}


function reactivateTags(){//not connected yet
	$.each(
		tags,
		function(tagId)
		{
			if(selectedItems[this.slug]){
				var vehicles = this.vehicles;
				for(i = 0; i<vehicles.length; i++){
					selectedItems[objetMobile[vehicles[i]].slug] = true;
				}
			}
		}
	);
	selection_has_changed = true;
}


/*****************************************************************/




/************** PARTIE  MENU  TABS  ******************************/

var tabs = {};//dans l'objet tabs, on trouve les champs: name, selectedItems, à partir duquel on peut reconstruire tous les autres.
var nbTabs = 0;

function saveTab(){
}

/*****************************************************************/






/************** PARTIE  MENU  OPTIONS  ***************************/

//ici, on devrait trouver des callbacks pour ajuster les paramètres de fonctionnement du suivi, charger les tabs

/*****************************************************************/


/********************************   END   CALLBACKS   *************************************************/



$(function initialise()
{
	document.getElementById("mosa").style.width = ""+Tx+"px";
	document.getElementById("mosa").style.height = ""+Ty+"px";
	//Cette fonction crée simplement les objets svg pour que l'on puisse les manipuler après.
	$('#mosa').svg();
	svg = $('#mosa').svg('get');
	imageSVGgroup = svg.group(null, {});
	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
			imageSVG[4*j+i] = svg.image(imageSVGgroup,i*Tx,j*Ty,Tx,Ty,"",{});
		}
	}
	imageSVGfondugroup = svg.group(null, {});
	tronconSVGgroup = svg.group(null, {});
	
	if (inDjango) {
		//requete pour récupérer les données suivantes:
		//itineraires, sous quelque forme que ce soit.
		
		$.getJSON(
			'/track/ajax/itineraries/',
			// This function is executed once the ajax query completes
			function(data)
			{
				// data is an array that associates ids to two-element arrays
				nbItineraires = 0;
				itineraire = {};
				
				$.each(
					data,
					function(id)
					{
						nbItineraires++;
						itineraire[id] = {
							name : this['name'],
							points : {},
							svg : []
						};
						nbCheckpoints = 0;
						
						$.each(
							checkpoints,
							function(j)
							{
								itineraire[id].points[j] = {
									x: checkpoints[j][0],
									y: checkpoints[j][1]
								};
								nbCheckpoints++;
							}
						);
						
						for(j=0; j<nbCheckpoints - 1; j++){
							itineraire[id].svg[j] = svg.line(tronconSVGgroup, 0, 0, 0, 0,{'stroke':"blue", 'stroke-width':1});
						}
					}
				);
				
				
				$.getJSON(
					'/track/ajax/vehicles/',
					// This function is executed once the ajax query completes
					function(data)
					{
						NombreObjets = 0;
						// data is an array that associates ids to two-element arrays
						$.each(
							data,
							function(id)
							{
								objetMobile[id] = {
									name: this.name,
									slug: this.slug,
									itinerary: this.itinerary,
									references: 0,
									lat: 0,
									lng: 0,
									id_checkpoint: -1,
									progression: 0,
									u: 0,
									v: 0,
									svg: svg.circle(pointSVGgroup, 0, 0, diametre, {fill:"blue"})
								};
								selected_vehicles[id] = 1;
								selectedItems[ objetMobile[id].slug ] = true;
								
								NombreObjets++;
							}
						);
						
						//récupérer tags[id_tag] = { name , nb_vehicles = 0 , vehicles = new Array() }
						$.getJSON(
							'/live/ajax/tags/',
							// This function is executed once the ajax query completes
							function(data)
							{ 
								$.each(
									data,
									function(id)
									{
										tags[id] = {
											name : this.name,
											slug : this.slug,
											is_mine : this.is_mine,
											is_public : this.is_public,
											nb_vehicles : 0,
											vehicles : new Array()
										};
										selectedItems[ tags[id].slug ] = false;
									}
								);
								
								//puis récupérer les couples (id_vehicle,id_tag)
								$.getJSON(
									'/live/ajax/vehicletags/',
									// This function is executed once the ajax query completes
									function(data)
									{ 
										$.each(
											data,
											function(id)
											{
												var tag_id = parseInt(this[1]);
												var v_id = parseInt(this[0]);
												tags[tag_id].vehicles[ tags[tag_id].nb_vehicles ] = v_id;
												tags[tag_id].nb_vehicles ++;
											}
										);
										
										//puis récupérer les positions.
										
										$.getJSON(
											'/track/ajax/positions/',
											// This function is executed once the ajax query completes
											function(data)
											{ 
												// data is an array that associates ids to two-element arrays
												$.each(
													data,
													function(id)
													{
														objetMobile[id].lng = parseFloat(this[0]);
														objetMobile[id].lat = parseFloat(this[1]);
														objetMobile[id].id_checkpoint = parseFloat(this[2]);
														objetMobile[id].progression = parseFloat(this[3]);//progression sur le tronçon entre 0 et 1
													}
												);
												
												bbox();
												
												actualiseStyleSelection();
												initialiseSuivi();
											}
										);
									}
								);
							}
						);
					}
				);
			}
		);
		
	}
	else{
		//on n'est pas dans django, on effectue une simulation.
		NombreObjets = 10;
		
		SelectionLng[0] = 2.347;
		SelectionLng[1] = 2.353;//pif paf pouf...
		
		SelectionLat[0] = 48.857;
		SelectionLat[1] = 48.863;//pif paf pouf...
		
		nbItineraires = 3;
		itineraire = {};
		
		var nbCheckpoints;
		for(i=0; i<nbItineraires; i++){
			nbCheckpoints = 4 + Math.round(6*Math.random());
			itineraire[i] = {
				name : 'itin_'+i+'_',
				points : {},
				svg : []
			};
			
			for(j=0; j<nbCheckpoints; j++){
				itineraire[i].points[j] = {
					x : SelectionLng[0] + 10*(Math.random())*(SelectionLng[1] - SelectionLng[0]),
					y : SelectionLat[0] + 10*(Math.random())*(SelectionLat[1] - SelectionLat[0])
				};
			}
			
			for(j=0; j<nbCheckpoints - 1; j++){
				itineraire[i].svg[j] = svg.line(tronconSVGgroup, 0, 0, 0, 0,{'stroke':"blue", 'stroke-width':1});
			}
		}
		
		for(i=0; i<NombreObjets; i++){
			objetMobile[i] = {
				lng: SelectionLng[0] + Math.random()*(SelectionLng[1] - SelectionLng[0]),
				lat: SelectionLat[0] + Math.random()*(SelectionLat[1] - SelectionLat[0]),
				references: 0,
				name: 'objetMobile_'+i+'_',
				slug: 'slug_'+i+'_'+Math.random(),
				itinerary: Math.round(nbItineraires*Math.random()),
				id_checkpoint: -1,
				progression: 0,
				u: 0,
				v: 0,
				svg: svg.circle(pointSVGgroup, 0, 0, diametre, {fill:"blue"})
			};
			
			selected_vehicles[i] = 1;
			selectedItems[objetMobile[i].slug] = true;
		}
		
		
		tags[0] = {
			name : 'equipe_1',
			slug : 'slug_tag_0_'+Math.random(),
			is_mine : true,
			is_public : true,
			nb_vehicles : 7,
			vehicles : new Array(0,1,2,3,4,5,6)
		};
		
		selectedItems[tags[0].slug] = false;
		
		actualiseStyleSelection();
		
		
		setInterval(function()
			{
				var rand;
				var front = 0.1 + 0.8*Math.random();
				/*
				for(i=0; i<NombreObjets; i++){
					rand = Math.random();
					if( rand < front ){
						console.log('rand = '+rand+'  ->  vehicule '+i+' ajouté');
						addVehicleToSelection(i);
					}
					else{
						console.log('rand = '+rand+'  ->  vehicule '+i+' déselectionné');
						deleteVehicleFromSelection(i);
					}
				}
				*/
				
				rand = Math.random();
				if( rand < 0.5 ){
					addTagToSelection(0);
				}
				else{
					deleteTagFromSelection(0);
				}
			},
			6000
		);
		
		initialiseSuivi();
	}
}
);


function actualiseStyleSelection(){
	$.each(
		objetMobile,
		function(id)
		{
			console.log('le vehicule '+id+' a '+objetMobile[id].references+' references');
			if(selected_vehicles[id]){
				(this.svg).setAttribute('fill','red');//après on les mettra avec une bordure rouge ou autre chose, on choisira...
			}
			else{
				(this.svg).setAttribute('fill','blue');//après on les mettra avec une bordure rouge ou autre chose, on choisira...
			}
		}
	);
}



function genereGPS(){
	//on doit enregistrer la precedente selection pour pouvoir faire une animation dans le cas où on change les cartes
	//(deplacer au nord par ex...)
	SelectionLng_prev[0] = SelectionLng[0];
	SelectionLng_prev[1] = SelectionLng[1];
	SelectionLat_prev[0] = SelectionLat[0];
	SelectionLat_prev[1] = SelectionLat[1];
	
	if (inDjango) {
		// Launch Ajax query to retrieve the current list of positions
		$.getJSON(
			'/track/ajax/positions/',
			// This function is executed once the ajax query completes
			function(data)
			{
				// data is an array that associates ids to two-element arrays
				$.each(
					data,
					function(id)
					{
						objetMobile[id].lng = parseFloat(this[0]);
						objetMobile[id].lat = parseFloat(this[1]);
						objetMobile[id].id_checkpoint = parseFloat(this[2]);
						objetMobile[id].progression = parseFloat(this[3]);
					}
				);
				
				setTimeout(suivi,(raffraichissement));
			}
		);
	}
	else{
		for (i = 0; i < NombreObjets; i++){
			objetMobile[i].lng += 0.002 - Math.random()*0.002;
			objetMobile[i].lat += 0.001 - Math.random()*0.002;
		}
		setTimeout(suivi,(raffraichissement));
	}
}


function bbox(){
	//on recalcule la bbox
	SelectionLat[0] = Infinity;
	SelectionLat[1] = -Infinity;
	SelectionLng[0] = Infinity;
	SelectionLng[1] = -Infinity;
	$.each(
		objetMobile,
		function(id)
		{
			if(selected_vehicles[id]){
				SelectionLat[0] = Math.min(SelectionLat[0], this.lat);
				SelectionLng[0] = Math.min(SelectionLng[0], this.lng);
				SelectionLat[1] = Math.max(SelectionLat[1], this.lat);
				SelectionLng[1] = Math.max(SelectionLng[1], this.lng);
			}
		}
	);
	//ici PREMIER TEST: si on n'a rien de sélectionné, alors la bbox est infinie !! (gros problème...)
	if(SelectionLat[0] > 100){
		SelectionLng[0] = SelectionLng_prev[0];
		SelectionLng[1] = SelectionLng_prev[1];
		SelectionLat[0] = SelectionLat_prev[0];
		SelectionLat[1] = SelectionLat_prev[1];
	}
	
	var TailleLng = SelectionLng[1] - SelectionLng[0];
	var TailleLat = SelectionLat[1] - SelectionLat[0];
	
	var CentreSelectionLng = (SelectionLng[1] + SelectionLng[0])/2;
	var CentreSelectionLat = (SelectionLat[1] + SelectionLat[0])/2;
	
	//ici DEUXIEME TEST: si la bbox est trop petite on la réajuste... (notamment, si on a un seul objet sélectionné...)
	if(TailleLng < 0.003){
		TailleLng = 0.003;
		SelectionLng[0] = CentreSelectionLng - TailleLng/2;
		SelectionLng[1] = CentreSelectionLng + TailleLng/2;
	}
	if(TailleLat < 0.003){
		TailleLat = 0.003;
		SelectionLat[0] = CentreSelectionLat - TailleLat/2;
		SelectionLat[1] = CentreSelectionLat + TailleLat/2;
	}
}



function initialiseSuivi(){
	//on recalcule la bbox
	if(selection_has_changed){
		//on met a jour la selection a ce moment, pas avant
		$.each(
			objetMobile,
			function(id)
			{
				selected_vehicles[id] = 0;
				if(selectedItems[this.slug]){
					selected_vehicles[id] = 1;
				}
			}
		);
		actualiseStyleSelection();
		selection_has_changed = false;
	}
	
	bbox();
	
	var TailleLng = SelectionLng[1] - SelectionLng[0];
	var TailleLat = SelectionLat[1] - SelectionLat[0];
	
	var CentreSelectionLng = (SelectionLng[1] + SelectionLng[0])/2;
	var CentreSelectionLat = (SelectionLat[1] + SelectionLat[0])/2;
	
	
	//on calcule le zoom approprié à la taille de la sélection
	switch(modele){
		case 'google':
		var zoomLng = -1;
		var zoomLat = -1;
		var taillelng = 90*Tx/64;
		var taillelat = 90*Ty*Math.cos(Math.PI*CentreSelectionLat/180)/64;//approximatif mais très correct.
		
		//test des zooms disponibles pour cette position (A IMPLEMENTER)
		//boucles pour choisir le zoom approprié
		while(TailleLng <= taillelng*1.2){
			taillelng/=2;
			zoomLng++;
		}
		taillelng *= 2;
		while(TailleLat <= taillelat*1.2){
			taillelat/=2;
			zoomLat++;
		}
		taillelat *= 2;
		if(zoomLat <= zoomLng){
			zoom = zoomLat;
		}
		else{
			zoom = zoomLng;
		}
		if(zoom == -1){
			zoom ++;
		}
		
		case 'yahoo':
		break;
		
		default:
		break;
	}
	
	//puis on prend le centre de la sélection, et on trouve à quelle image il correspond (i,j dans le pavage) et où on met cette image dans la mosaique (dépend de l'offset... on essaie de mettre le centre de la sélection le plus au centre possible).
	var px = lngToPixel(CentreSelectionLng,zoom);
	var py = latToPixel(CentreSelectionLat,zoom);
	
	var Centre_Indice_x = Math.round(parseFloat(px)/parseFloat(Tx));
	var Centre_Indice_y = Math.round(parseFloat(py)/parseFloat(Ty));//Les INDICES de la fenetre contenant le centre.
	
	var Centre_Offset_x = px-Centre_Indice_x*Tx;//différent de modulo Tx
	var Centre_Offset_y = py-Centre_Indice_y*Ty;//différent de modulo Ty
	
	var NewLng = pixelToLng(Centre_Indice_x*Tx , zoom);
	var NewLat = pixelToLat(Centre_Indice_y*Ty , zoom);
	
	//Maintenant, suivant les signes des offsets, on décide de l'emplacement de la fenetre contenant le centre: im22, im23, im32 ou im33
	initialiseUrls(Centre_Indice_x,Centre_Indice_y,Centre_Offset_x,Centre_Offset_y,NewLng,NewLat,zoom,0);
	//0 pour ant=0, on n'anticipe pas, on execute. ant=1 -> on anticipe (déclenchera un chargement des images dans les objets js images)
	
	//puis on se lance sur un régime de routine.
	genereGPS();
}





function suivi(){
	//on recalcule la bbox
	if(selection_has_changed){
		//on met a jour la selection a ce moment, pas avant
		$.each(
			objetMobile,
			function(id)
			{
				selected_vehicles[id] = 0;
				if(selectedItems[this.slug]){
					selected_vehicles[id] = 1;
				}
			}
		);
		actualiseStyleSelection();
		selection_has_changed = false;
	}
	bbox();
	
	//on situe la bbox
	var plat = latToPixel(SelectionLat[0],zoom);
	var pLat = latToPixel(SelectionLat[1],zoom);
	var plng = lngToPixel(SelectionLng[0],zoom);
	var pLng = lngToPixel(SelectionLng[1],zoom);
	
	var D_lat = pLat - plat;
	var D_lng = pLng - plng;
	
	
	if(D_lat > 1.3*Ty || D_lng > 1.3*Tx){
		if(D_lat > 1.8*Ty || D_lng > 1.8*Tx){
			//c'est la contrainte la plus importante: le plus important est qu'on doit voir toute la sélection.
			fondu = 1;
			initialiseSuivi();
			return;
			//On va voir ce que ça va faire, si ça se trouve ce sera aussi simple de refaire le travail en se disant que les urls
			//auront deja ete appelees, et que donc les images seront deja en local...
		}
		else{
			prepareUrls(-1,plat,pLat,plng,pLng);//on dit qu'on prépare les urls pour un zoom décrémenté.
		}
	}
	if(D_lat < 0.8*Ty & D_lng < 0.8*Tx){
		if(D_lat < 0.55*Ty & D_lng < 0.55*Tx){
			fondu = 1;
			initialiseSuivi();
			return;
		}
		else{
			prepareUrls(1,plat,pLat,plng,pLng);//on dit qu'on prépare les urls pour un zoom décrémenté.
		}
	}
	
	//on calcule les images occupées par la bbox (en fonction du résultat -> deplacerImages__(); )
	
	var x = localX(plng);
	var y = localY(pLat);
	var X = localX(pLng);
	var Y = localY(plat);
	
	if(x > 4*Tx){//alors on s'est planté dans le suivi...
		//console.log('selection a droite du cadre !!!');
		fondu = -1;
		initialiseSuivi();
		return;
	}
	if(X < 0){//alors on s'est planté dans le suivi...
		//console.log('selection a gauche du cadre !!!');
		fondu = -1;
		initialiseSuivi();
		return;
	}
	if(y > 4*Ty){//alors on s'est planté dans le suivi...
		//console.log('selection en dessous du cadre !!!');
		fondu = -1;
		initialiseSuivi();
		return;
	}
	if(Y < 0){//alors on s'est planté dans le suivi...
		//console.log('selection au dessus du cadre !!!');
		fondu = -1;
		initialiseSuivi();
		return;
	}
	
	//maintenant on est sur que la bbox est à l'intérieur de l'écran, on va voir si on peut anticiper sa sortie (déplacer les images)
	var zx;
	var Zx;//designent les zones occupées en largeur (longitude)
	if(x<Tx){
		zx=1;
	}
	else{
		if(x<2*Tx){
			zx=2;
		}
		else{
			if(x<3*Tx){
				zx=3;
			}
			else{
				//console.log('on aurait du deplacer les images vers l\'ouest...');
				fondu = -1;
				initialiseSuivi();
				return;
			}
		}
	}
	if(X>3*Tx){
		Zx=4;
	}
	else{
		if(X>2*Tx){
			Zx=3;
		}
		else{
			if(X>Tx){
				Zx=2;
			}
			else{
				//console.log('on aurait du deplacer les images vers l\'est...');
				fondu = -1
				initialiseSuivi();
				return;
			}
		}
	}
	
	var zy;
	var Zy;//designent les zones occupées en largeur (longitude)
	if(y<Ty){
		zy=1;
	}
	else{
		if(y<2*Ty){
			zy=2;
		}
		else{
			if(y<3*Ty){
				zy=3;
			}
			else{
				//console.log('on aurait du deplacer les images vers le nord...');
				fondu = -1
				initialiseSuivi();
				return;
			}
		}
	}
	if(Y>3*Ty){
		Zy=4;
	}
	else{
		if(Y>2*Ty){
			Zy=3;
		}
		else{
			if(Y>Ty){
				Zy=2;
			}
			else{
				//console.log('on aurait du deplacer les images vers le sud...');
				fondu = -1
				initialiseSuivi();
				return;
			}
		}
	}
	//maintenant on a comme info les zones occupées par la sélection, on va pouvoir déplacer les images en conséquence.
	var deplaceImages = 0;
	if((zx==1 & Zx==2)){
		deplacerImagesOuest();
		deplaceImages = 1;
	}
	else{
		if((zx==3 & Zx==4)){
			deplacerImagesEst();
			deplaceImages = 1;
		}
	}
	
	if((zy==1 & Zy==2)){
		deplacerImagesSud();
		deplaceImages = 1;
	}
	else{
		if((zy==3 & Zy==4)){
			deplacerImagesNord();
			deplaceImages = 1;
		}
	}
	
	if(deplaceImages == 1){
		appliqueUrls(0);
		return;
	}
	
	//on calcule la viewBox
	var Dx;
	var Dy;
	x = localX(plng);
	y = localY(pLat);//le coin supérieur gauche de la sélection
	
	if( D_lat < D_lng*Ty/Tx ){
		//alors on se base sur D_lng pour établir la viewBox
		Dx = Math.floor(1.1*D_lng);
		Dy = Math.floor(1.1*D_lng*Ty/Tx);
		x-= 0.05*D_lng;
		y+= 0.5*D_lat - 0.55*D_lng*Ty/Tx;
	}
	else{
		Dy = Math.floor(1.1*D_lat);
		Dx = Math.floor(1.1*D_lat*Tx/Ty);
		x+= 0.5*D_lng - 0.55*D_lat*Tx/Ty;
		y-= 0.05*D_lat;
	}
	
	setViewBox(x,y,Dx,Dy);
	
	genereGPS();
}





function setViewBox(x,y,Dx,Dy){
	//console.log("animation de viewBox vers: "+x+" "+y+" "+Dx+" "+Dy);
	
	var w = Math.round(Tx*Tx/Dx);
	var h = Math.round(Ty*Ty/Dy);
	var x2 = -x*Tx/Dx;
	var y2 = -y*Ty/Dy;
	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
			$(imageSVG[4*j+i]).animate({'svg-x': x2+i*w, 'svg-y': y2+j*h, 'svg-width': w, 'svg-height': h},500,'linear');
		}
	}
	
	$.each(
		objetMobile,
		function(id)
		{
			var x_obj = lngToPixel(this.lng,zoom);
			var y_obj = latToPixel(this.lat,zoom);
			
			x_obj = parseInt(localX(x_obj));
			y_obj = parseInt(localY(y_obj));
			this.u = Math.round((x_obj-x)*Tx/Dx);
			this.v = Math.round((y_obj-y)*Ty/Dy);
			$(this.svg).animate({'svg-cx': this.u, 'svg-cy': this.v},500,'linear');
		}
	);
	
	//NOUVELLEMENT:
	$.each(
		itineraire,
		function(id)
		{
			var x1;
			var x2;
			var y1;
			var y2;
			$.each(
				this.points,
				function(j)
				{
					if(j>0){
						x2 = lngToPixel(this.x,zoom);
						y2 = latToPixel(this.y,zoom);
						x2 = Math.round((parseInt(localX(x2))-x)*Tx/Dx);
						y2 = Math.round((parseInt(localY(y2))-y)*Ty/Dy);
						
						$(itineraire[id].svg[j-1]).animate({'svg-x1': x1, 'svg-x2': x2, 'svg-y1': y1, 'svg-y2': y2},500,'linear');
						
						x1 = x2;
						y1 = y2;
					}
					else{
						x1 = lngToPixel(this.x,zoom);
						y1 = latToPixel(this.y,zoom);
						x1 = Math.round((parseInt(localX(x1))-x)*Tx/Dx);
						y1 = Math.round((parseInt(localY(y1))-y)*Ty/Dy);
					}
				}
			);
		}
	);
	// C'est vraiment débile, mais on ne peut pas animer la viewBox avec jquery.svg, ni animer la taille du groupe d'images... :(
}



function prepareUrls(inc,plat,pLat,plng,pLng){
	
	if(inc==1){//on incrémente le zoom
		
		var CentreSelectionLng = (SelectionLng[0] + SelectionLng[1])/2;
		var CentreSelectionLat = (SelectionLat[0] + SelectionLat[1])/2;
		
		var px = lngToPixel(CentreSelectionLng,incrementeZoom(zoom));
		var py = latToPixel(CentreSelectionLat,incrementeZoom(zoom));
		
		var Centre_Indice_x = Math.round(parseFloat(px)/parseFloat(Tx));
		var Centre_Indice_y = Math.round(parseFloat(py)/parseFloat(Ty));//Les INDICES de la fenetre contenant le centre.
		
		//console.log('preparation des images: zoom a '+zoom+'+1  i_x '+Centre_Indice_x+'  i_y '+Centre_Indice_y);
		
		var Centre_Offset_x = px-Centre_Indice_x*Tx;//différent de modulo Tx
		var Centre_Offset_y = py-Centre_Indice_y*Ty;//différent de modulo Ty
		
		var NewLng = pixelToLng(Centre_Indice_x*Tx , incrementeZoom(zoom));
		var NewLat = pixelToLat(Centre_Indice_y*Ty , incrementeZoom(zoom));
		
		if((indice_prepare_x != Centre_Indice_x || indice_prepare_y != Centre_Indice_y) || zoom_prepare!=incrementeZoom(zoom)){
			indice_prepare_x = Centre_Indice_x;
			indice_prepare_y = Centre_Indice_y;
			zoom_prepare = incrementeZoom(zoom);
			initialiseUrls(Centre_Indice_x,Centre_Indice_y,Centre_Offset_x,Centre_Offset_y,NewLng,NewLat,incrementeZoom(zoom),1);
		}
		
		
	}
	else{//on décrémente le zoom
		
		var CentreSelectionLng = (SelectionLng[0] + SelectionLng[1])/2;
		var CentreSelectionLat = (SelectionLat[0] + SelectionLat[1])/2;
		
		var px = lngToPixel(CentreSelectionLng,decrementeZoom(zoom));
		var py = latToPixel(CentreSelectionLat,zoom-1);
		
		var Centre_Indice_x = Math.round(parseFloat(px)/parseFloat(Tx));
		var Centre_Indice_y = Math.round(parseFloat(py)/parseFloat(Ty));//Les INDICES de la fenetre contenant le centre.
		
		//console.log('preparation des images: dezoom a '+zoom+'-1  lng: '+CentreSelectionLng+'   lat: '+CentreSelectionLat);
		
		var Centre_Offset_x = px-Centre_Indice_x*Tx;//différent de modulo Tx
		var Centre_Offset_y = py-Centre_Indice_y*Ty;//différent de modulo Ty
		
		var NewLng = pixelToLng(Centre_Indice_x*Tx , decrementeZoom(zoom));
		var NewLat = pixelToLat(Centre_Indice_y*Ty , decrementeZoom(zoom));
		
		if((indice_prepare_x != Centre_Indice_x || indice_prepare_y != Centre_Indice_y) || zoom_prepare!=decrementeZoom(zoom)){
			indice_prepare_x = Centre_Indice_x;
			indice_prepare_y = Centre_Indice_y;
			zoom_prepare = decrementeZoom(zoom);
			initialiseUrls(Centre_Indice_x,Centre_Indice_y,Centre_Offset_x,Centre_Offset_y,NewLng,NewLat,decrementeZoom(zoom),1);
		}
	}
}


function localX(p){
	return Math.floor(Tx/2) + p - IndiceIM11_x*Tx;//renvoie une valeur entre 0 et 4Tx, d'après les imagettes présentes dans la mosaique
}
function localY(p){
	return Math.floor(Ty/2) - p + IndiceIM11_y*Ty;//renvoie une valeur entre 0 et 4Ty, d'après les imagettes présentes dans la mosaique
}


function deplacerImagesOuest(){
	//console.log('deplacement des images vers l\'ouest');
	
	IndiceIM11_x--;
	imagesUrls[3] = imagesUrls[2];
	imagesUrls[2] = imagesUrls[1];
	imagesUrls[1] = imagesUrls[0];
	imagesUrls[0] = url(IndiceIM11_x,IndiceIM11_y,zoom);
	imagesUrls[7] = imagesUrls[6];
	imagesUrls[6] = imagesUrls[5];
	imagesUrls[5] = imagesUrls[4];
	imagesUrls[4] = url(IndiceIM11_x,IndiceIM11_y-1,zoom);
	imagesUrls[11] = imagesUrls[10];
	imagesUrls[10] = imagesUrls[9];
	imagesUrls[9] = imagesUrls[8];
	imagesUrls[8] = url(IndiceIM11_x,IndiceIM11_y-2,zoom);
	imagesUrls[15] = imagesUrls[14];
	imagesUrls[14] = imagesUrls[13];
	imagesUrls[13] = imagesUrls[12];
	imagesUrls[12] = url(IndiceIM11_x,IndiceIM11_y-3,zoom);
}




function deplacerImagesEst(){
	//console.log('deplacement des images vers l\'est');
	
	IndiceIM11_x++;
	imagesUrls[0] = imagesUrls[1];
	imagesUrls[1] = imagesUrls[2];
	imagesUrls[2] = imagesUrls[3];
	imagesUrls[3] = url(IndiceIM11_x+3,IndiceIM11_y,zoom);
	imagesUrls[4] = imagesUrls[5];
	imagesUrls[5] = imagesUrls[6];
	imagesUrls[6] = imagesUrls[7];
	imagesUrls[7] = url(IndiceIM11_x+3,IndiceIM11_y-1,zoom);
	imagesUrls[8] = imagesUrls[9];
	imagesUrls[9] = imagesUrls[10];
	imagesUrls[10] = imagesUrls[11];
	imagesUrls[11] = url(IndiceIM11_x+3,IndiceIM11_y-2,zoom);
	imagesUrls[12] = imagesUrls[13];
	imagesUrls[13] = imagesUrls[14];
	imagesUrls[14] = imagesUrls[15];
	imagesUrls[15] = url(IndiceIM11_x+3,IndiceIM11_y-3,zoom);
}




function deplacerImagesSud(){
	//console.log('deplacement des images vers le sud');
	
	IndiceIM11_y++;
	imagesUrls[12] = imagesUrls[8];
	imagesUrls[8] = imagesUrls[4];
	imagesUrls[4] = imagesUrls[0];
	imagesUrls[0] = url(IndiceIM11_x,IndiceIM11_y,zoom);
	imagesUrls[13] = imagesUrls[9];
	imagesUrls[9] = imagesUrls[5];
	imagesUrls[5] = imagesUrls[1];
	imagesUrls[1] = url(IndiceIM11_x+1,IndiceIM11_y,zoom);
	imagesUrls[14] = imagesUrls[10];
	imagesUrls[10] = imagesUrls[6];
	imagesUrls[6] = imagesUrls[2];
	imagesUrls[2] = url(IndiceIM11_x+2,IndiceIM11_y,zoom);
	imagesUrls[15] = imagesUrls[11];
	imagesUrls[11] = imagesUrls[7];
	imagesUrls[7] = imagesUrls[3];
	imagesUrls[3] = url(IndiceIM11_x+3,IndiceIM11_y,zoom);
}




function deplacerImagesNord(){
	//console.log('deplacement des images vers le nord');
	
	IndiceIM11_y--;
	imagesUrls[0] = imagesUrls[4];
	imagesUrls[4] = imagesUrls[8];
	imagesUrls[8] = imagesUrls[12];
	imagesUrls[12] = url(IndiceIM11_x,IndiceIM11_y-3,zoom);
	imagesUrls[1] = imagesUrls[5];
	imagesUrls[5] = imagesUrls[9];
	imagesUrls[9] = imagesUrls[13];
	imagesUrls[13] = url(IndiceIM11_x+1,IndiceIM11_y-3,zoom);
	imagesUrls[2] = imagesUrls[6];
	imagesUrls[6] = imagesUrls[10];
	imagesUrls[10] = imagesUrls[14];
	imagesUrls[14] = url(IndiceIM11_x+2,IndiceIM11_y-3,zoom);
	imagesUrls[3] = imagesUrls[7];
	imagesUrls[7] = imagesUrls[11];
	imagesUrls[11] = imagesUrls[15];
	imagesUrls[15] = url(IndiceIM11_x+3,IndiceIM11_y-3,zoom);
}




function url(i_x,i_y,z){
	switch(modele){
		case 'google':
		if (inDjango) {
			return '/map/get/google/'+ Tx + '/' + Ty + '/' + pixelToLat(i_y * Ty, z) + '/' + pixelToLng(i_x * Tx, z) + '/' + z + '/';
		}
		else{
			return "http://maps.google.com/staticmap?center="+pixelToLat(i_y*Ty,z)+","+pixelToLng(i_x*Tx,z)+"&zoom="+z+"&size="+Tx+"x"+Ty+"&key="+ggkey;
		}
		break;
		
		case 'yahoo':
		if (inDjango) {
			return '/map/get/yahoo/'+ Tx + '/' + Ty + '/' + pixelToLat(i_y * Ty, z) + '/' + pixelToLng(i_x * Tx, z) + '/' + z + '/';
		}
		else{
			url = "http://maps.google.com/staticmap?center="+pixelToLat(i_y*Ty,z)+","+pixelToLng(i_x*Tx,z)+"&zoom="+z+"&size="+Tx+"x"+Ty+"&key="+ggkey;
			return url;
		}
		break;
		
		default:
		return "";
	}
}



function incrementeZoom(){
	switch(modele){
		case 'google':
		return zoom+1;
		break;
		
		case 'yahoo':
		return zoom-1;
		break;
		
		default:
		return zoom+1;
	}
}


function decrementeZoom(){
	switch(modele){
		case 'google':
		return zoom-1;
		break;
		
		case 'yahoo':
		return zoom+1;
		break;
		
		default:
		return zoom-1;
	}
}



function initialiseUrls(i_x,i_y,off_x,off_y,lng,lat,z,ant){
	if(ant==0){
		if(off_x<0){
			if(off_y<0){
				//on met le centre dans im23
				IndiceIM11_x = i_x-2;
				IndiceIM11_y = i_y+1;
			}
			else{
				//on met le centre dans im33
				IndiceIM11_x = i_x-2;
				IndiceIM11_y = i_y+2;
			}
		}
		else{
			if(off_y<0){
				//on met le centre dans im22
				IndiceIM11_x = i_x-1;
				IndiceIM11_y = i_y+1;
			}
			else{
				//on met le centre dans im32
				IndiceIM11_x = i_x-1;
				IndiceIM11_y = i_y+2;
			}
		}
		
		imagesUrls[0] = url(IndiceIM11_x,IndiceIM11_y,z)
		imagesUrls[1] = url(IndiceIM11_x+1,IndiceIM11_y,z);
		imagesUrls[2] = url(IndiceIM11_x+2,IndiceIM11_y,z);
		imagesUrls[3] = url(IndiceIM11_x+3,IndiceIM11_y,z);
		imagesUrls[4] = url(IndiceIM11_x,IndiceIM11_y-1,z)
		imagesUrls[5] = url(IndiceIM11_x+1,IndiceIM11_y-1,z);
		imagesUrls[6] = url(IndiceIM11_x+2,IndiceIM11_y-1,z);
		imagesUrls[7] = url(IndiceIM11_x+3,IndiceIM11_y-1,z);
		imagesUrls[8] = url(IndiceIM11_x,IndiceIM11_y-2,z)
		imagesUrls[9] = url(IndiceIM11_x+1,IndiceIM11_y-2,z);
		imagesUrls[10] = url(IndiceIM11_x+2,IndiceIM11_y-2,z);
		imagesUrls[11] = url(IndiceIM11_x+3,IndiceIM11_y-2,z);
		imagesUrls[12] = url(IndiceIM11_x,IndiceIM11_y-3,z)
		imagesUrls[13] = url(IndiceIM11_x+1,IndiceIM11_y-3,z);
		imagesUrls[14] = url(IndiceIM11_x+2,IndiceIM11_y-3,z);
		imagesUrls[15] = url(IndiceIM11_x+3,IndiceIM11_y-3,z);
		
		appliqueUrls(ant);
	}
	else{//alors c'est qu'on anticipe.
		var ind_x;
		var ind_y;
		if(off_x<0){
			if(off_y<0){
				//on met le centre dans im23
				ind_x = i_x-2;
				ind_y = i_y+1;
			}
			else{
				//on met le centre dans im33
				ind_x = i_x-2;
				ind_y = i_y+2;
			}
		}
		else{
			if(off_y<0){
				//on met le centre dans im22
				ind_x = i_x-1;
				ind_y = i_y+1;
			}
			else{
				//on met le centre dans im32
				ind_x = i_x-1;
				ind_y = i_y+2;
			}
		}
		
		imagesUrls[16] = url(ind_x,ind_y,z)
		imagesUrls[17] = url(ind_x+1,ind_y,z);
		imagesUrls[18] = url(ind_x+2,ind_y,z);
		imagesUrls[19] = url(ind_x+3,ind_y,z);
		imagesUrls[20] = url(ind_x,ind_y-1,z)
		imagesUrls[21] = url(ind_x+1,ind_y-1,z);
		imagesUrls[22] = url(ind_x+2,ind_y-1,z);
		imagesUrls[23] = url(ind_x+3,ind_y-1,z);
		imagesUrls[24] = url(ind_x,ind_y-2,z)
		imagesUrls[25] = url(ind_x+1,ind_y-2,z);
		imagesUrls[26] = url(ind_x+2,ind_y-2,z);
		imagesUrls[27] = url(ind_x+3,ind_y-2,z);
		imagesUrls[28] = url(ind_x,ind_y-3,z)
		imagesUrls[29] = url(ind_x+1,ind_y-3,z);
		imagesUrls[30] = url(ind_x+2,ind_y-3,z);
		imagesUrls[31] = url(ind_x+3,ind_y-3,z);
		
		appliqueUrls(ant);
	}
}





function appliqueUrls(ant){
	if(ant==0){
		var plat = latToPixel(SelectionLat[0],zoom);
		var pLat = latToPixel(SelectionLat[1],zoom);
		var plng = lngToPixel(SelectionLng[0],zoom);
		var pLng = lngToPixel(SelectionLng[1],zoom);
		
		var D_lat = pLat - plat;
		var D_lng = pLng - plng;
		
		var Dx;
		var Dy;
		var x = localX(plng);
		var y = localY(pLat);
		
		if( D_lat < D_lng*Ty/Tx ){
			//alors on se base sur D_lng pour établir la viewBox
			Dx = Math.floor(1.1*D_lng);
			Dy = Math.floor(1.1*D_lng*Ty/Tx);
			x-= 0.05*D_lng;
			y+= 0.5*D_lat - 0.55*D_lng*Ty/Tx;
		}
		else{
			Dy = Math.floor(1.1*D_lat);
			Dx = Math.floor(1.1*D_lat*Tx/Ty);
			x+= 0.5*D_lng - 0.55*D_lat*Tx/Ty;
			y-= 0.05*D_lat;
		}
		
		var w = Math.round(Tx*Tx/Dx);
		var h = Math.round(Ty*Ty/Dy);
		var x2 = -x*Tx/Dx;
		var y2 = -y*Ty/Dy;
		
		switch(fondu){
			case 1:
			
			for(i=0; i<4; i++){
				for(j=0; j<4; j++){
					imageSVGfondu[4*j+i] = imageSVG[4*j+i];
					imageSVG[4*j+i] = svg.image(imageSVGgroup,x2+i*w,y2+j*h,w,h,imagesUrls[4*j+i],{'opacity':0});
				}
			}
			setTimeout(function(){setfondu(0);},500);
			//safari est très lent pour le changement des images, alors on lui dit d'attendre le chargement complet
			//avant de faire le fondu.
			fondu = 0;
			
			var iter = 0;
			
			$.each(
				objetMobile,
				function(id)
				{
					var x_obj = lngToPixel(this.lng,zoom);
					var y_obj = latToPixel(this.lat,zoom);
					
					x_obj = parseInt(localX(x_obj));
					y_obj = parseInt(localY(y_obj));
					this.u = Math.round((x_obj-x)*Tx/Dx);
					this.v = Math.round((y_obj-y)*Ty/Dy);
				}
			);
			
			setTimeout(
				function()
				{
					$.each(
						objetMobile,
						function(id)
						{
							$(this.svg).animate({'svg-cx': this.u, 'svg-cy': this.v},500,'linear');
						}
					);
					
					//NOUVELLEMENT:
					$.each(
						itineraire,
						function(id)
						{
							var x1;
							var x2;
							var y1;
							var y2;
							$.each(
								this.points,
								function(j)
								{
									if(j>0){
										x2 = lngToPixel(this.x,zoom);
										y2 = latToPixel(this.y,zoom);
										x2 = Math.round((parseInt(localX(x2))-x)*Tx/Dx);
										y2 = Math.round((parseInt(localY(y2))-y)*Ty/Dy);
										
										svg.remove(itineraire[id].svg[j-1]);
										itineraire[id].svg[j-1] = svg.line(tronconSVGgroup, x1, y1, x2, y2,{'stroke':"blue", 'stroke-width':1});
										
										x1 = x2;
										y1 = y2;
									}
									else{
										x1 = lngToPixel(this.x,zoom);
										y1 = latToPixel(this.y,zoom);
										x1 = Math.round((parseInt(localX(x1))-x)*Tx/Dx);
										y1 = Math.round((parseInt(localY(y1))-y)*Ty/Dy);
									}
								}
							);
						}
					);
				},
				500
			);
			
			break;
			
			
			case 0:
			
			var plat_prev = latToPixel(SelectionLat_prev[0],zoom);
			var pLat_prev = latToPixel(SelectionLat_prev[1],zoom);
			var plng_prev = lngToPixel(SelectionLng_prev[0],zoom);
			var pLng_prev = lngToPixel(SelectionLng_prev[1],zoom);
			
			var D_lat_prev = pLat_prev - plat_prev;
			var D_lng_prev = pLng_prev - plng_prev;
			
			var Dx_prev;
			var Dy_prev;
			var x_prev = localX(plng_prev);
			var y_prev = localY(pLat_prev);
			
			if( D_lat_prev < D_lng_prev*Ty/Tx ){
				//alors on se base sur D_lng pour établir la viewBox
				Dx_prev = Math.floor(1.1*D_lng_prev);
				Dy_prev = Math.floor(1.1*D_lng_prev*Ty/Tx);
				x_prev-= 0.05*D_lng_prev;
				y_prev+= 0.5*D_lat_prev - 0.55*D_lng_prev*Ty/Tx;
			}
			else{
				Dy_prev = Math.floor(1.1*D_lat_prev);
				Dx_prev = Math.floor(1.1*D_lat_prev*Tx/Ty);
				x_prev+= 0.5*D_lng_prev - 0.55*D_lat_prev*Tx/Ty;
				y_prev-= 0.05*D_lat_prev;
			}
			var w_prev = Math.round(Tx*Tx/Dx_prev);
			var h_prev = Math.round(Ty*Ty/Dy_prev);
			var x2_prev = -x_prev*Tx/Dx_prev;
			var y2_prev = -y_prev*Ty/Dy_prev;
			for(i=0; i<4; i++){
				for(j=0; j<4; j++){
					imageSVGfondu[4*j+i] = svg.image(imageSVGfondugroup,x2_prev+i*w_prev,y2_prev+j*h_prev,w_prev,h_prev,imagesUrls[4*j+i],{'opacity':0});
				}
			}
			$.each(
				objetMobile,
				function(id)
				{
					svg.remove(this.svg);
					this.svg = svg.circle(pointSVGgroup, this.u, this.v, diametre, {fill:"blue"});
				}
			);
			
			actualiseStyleSelection();
			
			setTimeout(
				function(){
					for(i=0; i<4; i++){
						for(j=0; j<4; j++){
							imageSVGfondu[4*j+i].setAttribute('opacity',1);
						}
					}
					setTimeout(
						function(){
							for(i=0; i<4; i++){
								for(j=0; j<4; j++){
									svg.remove(imageSVG[4*j+i]);
								}
							}
							for(i=0; i<4; i++){
								for(j=0; j<4; j++){
									imageSVG[4*j+i] = imageSVGfondu[4*j+i];
									$(imageSVG[4*j+i]).animate({'svg-x': x2+i*w, 'svg-y': y2+j*h,'svg-width': w,'svg-height':h},500,'linear');
								}
							}
							
							$.each(
								objetMobile,
								function(id)
								{
									var x_obj = lngToPixel(this.lng,zoom);
									var y_obj = latToPixel(this.lat,zoom);
									
									x_obj = parseInt(localX(x_obj));
									y_obj = parseInt(localY(y_obj));
									this.u = Math.round((x_obj-x)*Tx/Dx);
									this.v = Math.round((y_obj-y)*Ty/Dy);
									$(this.svg).animate({'svg-cx': this.u, 'svg-cy': this.v},500,'linear');
								}
							);
							
							//NOUVELLEMENT:
							$.each(
								itineraire,
								function(id)
								{
									var xx1;
									var xx2;
									var yy1;
									var yy2;
									$.each(
										this.points,
										function(j)
										{
											if(j>0){
												xx2 = lngToPixel(this.x,zoom);
												yy2 = latToPixel(this.y,zoom);
												xx2 = Math.round((parseInt(localX(xx2))-x)*Tx/Dx);
												yy2 = Math.round((parseInt(localY(yy2))-y)*Ty/Dy);
												
												$(itineraire[id].svg[j-1]).animate({'svg-x1': xx1, 'svg-x2': xx2, 'svg-y1': yy1, 'svg-y2': yy2},500,'linear');
												
												xx1 = xx2;
												yy1 = yy2;
											}
											else{
												xx1 = lngToPixel(this.x,zoom);
												yy1 = latToPixel(this.y,zoom);
												xx1 = Math.round((parseInt(localX(xx1))-x)*Tx/Dx);
												yy1 = Math.round((parseInt(localY(yy1))-y)*Ty/Dy);
											}
										}
									);
								}
							);
							
							genereGPS();
						},
						500//le temps qu'on laisse a safari pour changer l'opacité 8-|
					);
				},
				1500//le temps qu'on laisse a safari pour changer les images à l'aide du dom...  X-(
			);
			
			break;
			
			
			case -1:
			
			for(i=0; i<4; i++){
				for(j=0; j<4; j++){
					imageSVG[4*j+i].setAttribute('x',x2+i*w);
					imageSVG[4*j+i].setAttribute('y',y2+j*h);
					imageSVG[4*j+i].setAttribute('width',w);
					imageSVG[4*j+i].setAttribute('height',h);
					imageSVG[4*j+i].setAttribute('href',imagesUrls[4*j+i]);
				}
			}
			
			var iter = 0;
			
			$.each(
				objetMobile,
				function(id)
				{
					var x_obj = lngToPixel(this.lng,zoom);
					var y_obj = latToPixel(this.lat,zoom);
					
					x_obj = parseInt(localX(x_obj));
					y_obj = parseInt(localY(y_obj));
					this.u = Math.round((x_obj-x)*Tx/Dx);
					this.v = Math.round((y_obj-y)*Ty/Dy);
					$(this.svg).animate({'svg-cx': this.u, 'svg-cy': this.v},500,'linear');
				}
			);
			
			//NOUVELLEMENT:
			$.each(
				itineraire,
				function(id)
				{
					var x1;
					var x2;
					var y1;
					var y2;
					$.each(
						this.points,
						function(j)
						{
							if(j>0){
								x2 = lngToPixel(this.x,zoom);
								y2 = latToPixel(this.y,zoom);
								x2 = Math.round((parseInt(localX(x2))-x)*Tx/Dx);
								y2 = Math.round((parseInt(localY(y2))-y)*Ty/Dy);
								
								$(itineraire[id].svg[j-1]).animate({'svg-x1': x1, 'svg-x2': x2, 'svg-y1': y1, 'svg-y2': y2},500,'linear');
								
								x1 = x2;
								y1 = y2;
							}
							else{
								x1 = lngToPixel(this.x,zoom);
								y1 = latToPixel(this.y,zoom);
								x1 = Math.round((parseInt(localX(x1))-x)*Tx/Dx);
								y1 = Math.round((parseInt(localY(y1))-y)*Ty/Dy);
							}
						}
					);
				}
			);
			
			fondu = 0;
			break;
		}
	}
	else{//c'est qu'on anticipe.
		for(j=0; j<16; j++){
			imagePreparees[j] = new Image();
			imagePreparees[j].src = imagesUrls[j+16];
			imagePreparees[j].onload = function(){delete imagePreparees[j]};
		}
	}
}


function setfondu(iter){
	if(iter==6){
		for(i=0; i<4; i++){
			for(j=0; j<4; j++){
				svg.remove(imageSVGfondu[4*j+i]);
			}
		}
		return;
	}
	else{
		for(i=0; i<4; i++){
			for(j=0; j<4; j++){
				imageSVGfondu[4*j+i].setAttribute('opacity',1-iter/5);
				imageSVG[4*j+i].setAttribute('opacity',iter/5);
			}
		}
		setTimeout(function(){setfondu(iter+1);},100);
	}
}


//NOTE :
//Les fonctions qui suivent supposent que les fonctions sin, tan, atan , effectuent les calculs en radians et non pas en degrés.

function lngToPixel(lng,z){
	switch(modele){
		case 'google':
		var puis = 64;
		for(i=0; i<z; i++){
			puis*=2;
		}
		return parseInt( lng*puis/90 );
		
		case 'yahoo':
		return 0;
		
		default:
		return 0;
	}
}


function latToPixel(lat,z){
	switch(modele){
		case 'google':
		var puis = 64;
		for(i=0; i<z; i++){
			puis*=2;
		}	
		//return parseInt( puis*ln( (1+sin(pi*lat/180) )/(1-sin(pi*lat/180) ) )/pi );
		//ou alors c'est aussi égal à:
		return parseInt(  2*puis*Math.log( Math.tan(Math.PI/4 + Math.PI*lat/360) )/(Math.PI*Math.log(Math.E))  );
		
		case 'yahoo':
		return 0;
		
		default:
		return 0;
	}
}


function pixelToLng(p,z){
	switch(modele){
		case 'google':
		var puis = 64;
		for(i=0; i<z; i++){
			puis*=2;
		}
		return 90*p/puis;
		
		case 'yahoo':
		return 0;
		
		default:
		return 0;
	}
}


function pixelToLat(p,z){
	switch(modele){
		case 'google':
		var puis = 64;
		for(i=0; i<z; i++){
			puis*=2;
		}
		return 360*Math.atan(Math.exp(p*Math.PI/(2*puis)))/Math.PI - 90;
		
		case 'yahoo':
		return 0;
		
		default:
		return 0;
	}
}
